package com.ssm.collection.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
public class ApplicationContextHelper implements ApplicationContextAware, BeanFactoryAware, ServletContextAware {

	public static final String SERVICE_UNIT = "serviceUnit";

	private static ApplicationContext applicationContext;
	private static BeanFactory beanFactory;
	private static ServletContext servletContext;

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		// TODO Auto-generated method stub
		ApplicationContextHelper.beanFactory = beanFactory;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		// TODO Auto-generated method stub
		ApplicationContextHelper.applicationContext = applicationContext;
	}

	@Override
	public void setServletContext(ServletContext servletContext) {
		// TODO Auto-generated method stub
		ApplicationContextHelper.servletContext = servletContext;
	}

	public static ApplicationContext getContext() {
		return applicationContext;
	}

	public static BeanFactory getBeanFactory() {
		return beanFactory;
	}

	public static ServletContext getServletContext() {
		return servletContext;
	}

	public static <T> T getBean(Class<T> clazz, String serviceUnitId) {
		Map<String, T> beans = applicationContext.getBeansOfType(clazz);

		// 1. Bean of specified class not found
		if (beans.isEmpty()) {
			return null;
		}

		// 2. Just one bean implementation found
		if (beans.size() == 1) {
			return beans.values().iterator().next();
		}

		// 3. Bean with name containing specified service unit id exists
		for (String beanName : beans.keySet()) {
			if (beanName.toLowerCase().contains(serviceUnitId.toLowerCase())) {
				return beans.get(beanName);
			}
		}

		// 4. Default bean (shortest name)
		List<String> beanNames = new ArrayList<>(beans.keySet());
		Collections.sort(beanNames, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				// TODO Auto-generated method stub
				if (o1.length() > o2.length()) {
					return 1;
				} else if (o1.length() < o2.length()) {
					return -1;
				}
				return 0;
			}
		});
		return beans.get(beanNames.get(0));
	}

	public static HttpServletRequest getServletRequest() {
		RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
		if (attributes == null) {
			return null;
		}
		return ((ServletRequestAttributes) attributes).getRequest();
	}

	public static HttpSession getSession() {
		HttpServletRequest request = getServletRequest();
		if (request == null) {
			return null;
		}

		return request.getSession();
	}
}
